


#include "MyCan.h"


#include "Serial.h"
#include "TemperatureStuff.h"
#include "userConfig.h"
//Serial Commands:
//All end with \n
//Always ignore \r
//Are Case Sensitive
//? - request configuration information
//! - request temperature readings
//Vxxx - Set termination voltage (takes it as integer at 10* value, ex 100.1 termination would be sent as V1001)
//Cxxx - Set termination current
//M - enable master mode
//S - disable master mode
//Txxx - Set temperature threshold (takes it as integer for degrees celcius)
//Axxx - Set source Address (takes it as a decimal number)
//H - Sends hello world
//Ixxx - Set Internal Node Count
//Exxx - Set External Node Count
//@ - Request Charger Status
//# - Request current CAN status

typedef enum
{
    SS_IDLE,
    SS_READY_FOR_ACTION,
            SS_BUILD_PARAMETER,
    SS_ERROR
} SerialStates;

typedef void(*ActionFunctionDef)(void);

static SerialStates SerialState;
static int TemproraryVariableForCommand;
static ActionFunctionDef ActionFunction;

static void IdleState(char c);
static void ErrorState(char c);
static void ActionState(char c);
static void BuildParameterState(char c);

static void MoveToParameterState();

static void ss_RequestConfigurationInformation();
static void ss_SetLowTemperatureThreshold();
static void ss_SetHighTemperatureThreshold();
static void ss_SetCANAddress();
static void ss_SendCANStatus();
static void ss_SetExternalNodeCount();
static void ss_PrintTemperatureValues();

void InitSerialStateMachine()
{
    SerialState = SS_IDLE;
}

void ProcessCharacter(char c)
{
    if(c != '\n')
    {
        switch(SerialState)
        {
            case SS_IDLE:
                IdleState(c);
                break;
            case SS_READY_FOR_ACTION:
                ActionState(c);
                break;
            case SS_BUILD_PARAMETER:
                BuildParameterState(c);
                break;
            case SS_ERROR:
                ErrorState(c);
                break;
        }

        if(c == '\r')
        {
            SerialState = SS_IDLE;
        }
    }
}

void IdleState(char c)
{
    switch(c)
    {
        case '?':
            ActionFunction = &ss_RequestConfigurationInformation;
            SerialState = SS_READY_FOR_ACTION;
            break;
        case '#':
            ActionFunction = &ss_SendCANStatus;
            SerialState = SS_READY_FOR_ACTION;
            break;
        case '!':
            ActionFunction = &ss_PrintTemperatureValues;
            SerialState = SS_READY_FOR_ACTION;
            break;
        case 'L':
            ActionFunction = &ss_SetLowTemperatureThreshold;
            MoveToParameterState();
            break;
        case 'H':
            ActionFunction = &ss_SetHighTemperatureThreshold;
            MoveToParameterState();
            break;
        case 'A':
            ActionFunction = &ss_SetCANAddress;
            MoveToParameterState();
            break;
        case 'E':
            ActionFunction = &ss_SetExternalNodeCount;
            MoveToParameterState();
            break;
        default:
            SerialState = SS_ERROR;
    }
}

void ErrorState(char c)
{
}

void ActionState(char c)
{
    if(c == '\r')
    {
        ActionFunction();
    }
    else
    {
        SerialState = SS_ERROR;
    }
}

void MoveToParameterState()
{
    TemproraryVariableForCommand = 0;
    SerialState = SS_BUILD_PARAMETER;
}

void BuildParameterState(char c)
{
    if(c == '\r')
    {
        ActionFunction();
    }
    else if (c >= '0' && c <= '9')
    {
        int newOnesDigit = c - '0';
        TemproraryVariableForCommand *= 10;
        TemproraryVariableForCommand += newOnesDigit;
    }
    else
    {
        SerialState = SS_ERROR;
    }
}

void ss_RequestConfigurationInformation()
{
    PrintUserConfig();
}
void ss_SetLowTemperatureThreshold()
{
    SetLowTemperatureThreshold(TemproraryVariableForCommand);
}

void ss_SetHighTemperatureThreshold()
{
    SetHighTemperatureThreshold(TemproraryVariableForCommand);
}
void ss_SetCANAddress()
{
    SetCANAddress(TemproraryVariableForCommand);
}
void ss_SendCANStatus()
{
    MC_PrintCANStatus();
}
void ss_SetExternalNodeCount()
{
    SetExternalNodeCount(TemproraryVariableForCommand);
}
void ss_PrintTemperatureValues()
{
    PrintAllTemperatures();
}